﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

using DeloneTriangulate;
using MathVolume;

using System.Drawing.Drawing2D; // Добавить Кисти. SolidBrush

using System.Diagnostics;

namespace Triangula
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private List<Point[]> coordPointsLeftRight;     // Список линий (точек) по оси Y.
        private List<Point[]> coordPointsTopBottom;     // Список линий (точек) по оси X.

        private List<Color> colorsOfLayers;             // цвета слоев.
        private List<double[][]> triangles;             // исходные треугольники - слои.
        private List<int> operations;                   // тип операции по слоям.
        private List<double[][]> resultTriangles;       // малые треугольники после триангуляции
        private List<List<bool>> isInTriangle;          // [список слоев][список малых треугольников]<bool - принадлежность>
        private List<List<CoalLayer>> coalLayers;       // [список этапов][список слоев]<описание слоя>
        //private List<List<smallTriangleInfo>> boolTriangleList; // [список этапов][список малых треугольников]<параметры треугольника>

        private List<double[][]> trianglesTemp;         // исходные треугольники - слои. (для визуализации)
        private List<double[][]> resultTrianglesTemp;   // малые треугольники после триангуляции. (для визуализации)
        
        /// <summary>
        /// Определяет слой для визуацизации
        /// </summary>
        private class CoalLayer
        {
            public int id;                              // id слоя
            public List<double[][]> trianlges;          // список малых треугольников, его описывающих
            public Color color;                         // цвет слоя
            
            /// <summary>
            /// Конструктор.
            /// </summary>
            /// <param name="_id">id слоя</param>
            /// <param name="_trianlges">список малых треугольников, его описывающих</param>
            /// <param name="_color">цвет слоя</param>
            public CoalLayer(int _id, List<double[][]> _trianlges, Color _color)
            {
                id = _id;
                trianlges = new List<double[][]>(_trianlges);
                color = _color;
            }
        }

        /// <summary>
        /// Инфо-флаг малого треугольника.
        /// </summary>
        private class smallTriangleInfo : ICloneable
        {
            public bool enable;                         // треугольник используется
            public int id;                              // id слоя (большого треугольника) которому принадлежит
            public Color color;                         // цвет слоя, которому принадлежит

            /// <summary>
            /// Конструктор.
            /// </summary>
            /// <param name="_enable">треугольник используется</param>
            /// <param name="_id">id слоя (большого треугольника) которому принадлежит</param>
            /// <param name="_color">цвет слоя, которому принадлежит</param>
            public smallTriangleInfo(bool _enable, int _id, Color _color)
            {
                enable = _enable;
                id = _id;
                color = _color;
            }

            public object Clone()
            {
                smallTriangleInfo newObject = new smallTriangleInfo(enable, id, color);
                newObject = (smallTriangleInfo)this.MemberwiseClone();
                return newObject;
            }
        }

        private bool _compliete = false;                // флаг разрещающий перерисовку события OnPaint
        private bool _show = false;                     // флаг отображающий малые треугольники

        private int zoom;                               // коэффициент масштабирования координат.
        private int shiftV;                             // сдвиг координат по вертикали (pix)
        private int shiftH;                             // сдвиг координат по горизонтали (pix)
        private int Layer;                              // текущий этап.

        private int coordMaxX;                          // максимальное деление на координатной оси X.
        private int coordMaxY;                          // максимальное деление на координатной оси Y.

        private void MainForm_Load(object sender, EventArgs e)
        {
            _compliete = false;
            _show = false;
            zoom = 60;
            shiftV = 700;
            shiftH = -500;
            Layer = 17;

            coordMaxX = 30;
            coordMaxY = 30;

            tbZoom.Text = zoom.ToString();
            tbShiftH.Text = shiftH.ToString();
            tbShiftV.Text = shiftV.ToString();
            tbLayer.Text = Layer.ToString();

            tbMaxX.Text = coordMaxX.ToString();
            tbMaxY.Text = coordMaxY.ToString();

            triangles = new List<double[][]>();
            operations = new List<int>();

            // рассчитать коордианты вершин слоев + индексы операций.
            if (!MathVolume.TransformationData.sthFunc(ref triangles, ref operations))
            {
                throw new Exception("Ошибка расчетов.");
            }

            Stopwatch watch = new Stopwatch();
            watch.Start();
                // Триангуляция Делоне.
                resultTriangles = DeloneTriangulate.Actions.Triangulation.triangulate(triangles);
            watch.Stop();
            this.Text = "Триангуляция. [LeftMouseClick - показать/скрыть треугольники]. Построено за: " + watch.ElapsedMilliseconds.ToString() + " ms.";
            
            // определение принадлежности малых треугольников - большим треугольникам.
            isInTriangle = DeloneTriangulate.Actions.Triangulation.checkIsTriangleIn(resultTriangles, triangles);

            // задать цвета слоев.
            colorsOfLayers = new List<Color>();
            for (int i = 0; i < operations.Count; i++)
            {
                Random rand = new Random(DateTime.Now.Millisecond + i);

                int R = rand.Next(255);
                int G = rand.Next(255);
                int B = rand.Next(255);

                colorsOfLayers.Add(Color.FromArgb(R, G, B));
            }
                

            // сформировать слои для всех этапов.
            coalLayers = formationTheLayerList(colorsOfLayers, operations, resultTriangles, isInTriangle);

            // масштабирование 
            //shiftCoords();
            shiftCoordsCustom(Layer);
            //
            _compliete = true;
        }

        private void MainForm_Paint(object sender, PaintEventArgs e)
        {
            if (_compliete == true)
            {
                Graphics g = this.CreateGraphics();
                //
                Pen penEdge = new Pen(Color.SpringGreen, 2);
                // Линии:
                for (int i = 0; i < trianglesTemp.Count; i++)
                {
                    g.DrawLine(penEdge, (float)trianglesTemp[i][0][0], (float)trianglesTemp[i][0][1], (float)trianglesTemp[i][1][0], (float)trianglesTemp[i][1][1]);
                    g.DrawLine(penEdge, (float)trianglesTemp[i][1][0], (float)trianglesTemp[i][1][1], (float)trianglesTemp[i][2][0], (float)trianglesTemp[i][2][1]);
                    g.DrawLine(penEdge, (float)trianglesTemp[i][0][0], (float)trianglesTemp[i][0][1], (float)trianglesTemp[i][2][0], (float)trianglesTemp[i][2][1]);
                }
                if (_show == true)
                {
                    // Нарисовать закрашенные треугольники.
                    List<List<double[][]>> drawTriangles = getLayerList(coalLayers, Layer, zoom, shiftH, shiftV);
                    for (int n = 0; n < drawTriangles.Count; n++)
                    {
                        SolidBrush triangleBrush = new SolidBrush(colorsOfLayers[n]);
                        for (int i = 0; i < drawTriangles[n].Count; i++)
                        {
                            PointF[] points = new PointF[3];
                            points[0].X = (float)drawTriangles[n][i][0][0]; points[0].Y = (float)drawTriangles[n][i][0][1];
                            points[1].X = (float)drawTriangles[n][i][1][0]; points[1].Y = (float)drawTriangles[n][i][1][1];
                            points[2].X = (float)drawTriangles[n][i][2][0]; points[2].Y = (float)drawTriangles[n][i][2][1];

                            g.FillPolygon(triangleBrush, points);
                        }
                        triangleBrush.Dispose();
                    }
                    // Треугольники (черный контур):
                    if (chSmallT.Checked == true)
                    {
                        Pen penTriangle = new Pen(Color.Black, 1);
                        // 
                        for (int i = 0; i < resultTrianglesTemp.Count; i++)
                        {
                            g.DrawLine(penTriangle, (float)resultTrianglesTemp[i][0][0], (float)resultTrianglesTemp[i][0][1], (float)resultTrianglesTemp[i][1][0], (float)resultTrianglesTemp[i][1][1]);
                            g.DrawLine(penTriangle, (float)resultTrianglesTemp[i][1][0], (float)resultTrianglesTemp[i][1][1], (float)resultTrianglesTemp[i][2][0], (float)resultTrianglesTemp[i][2][1]);
                            g.DrawLine(penTriangle, (float)resultTrianglesTemp[i][0][0], (float)resultTrianglesTemp[i][0][1], (float)resultTrianglesTemp[i][2][0], (float)resultTrianglesTemp[i][2][1]);
                        }
                    }
                }
                // Точки:
                if (chPoints.Checked == true)
                {
                    Pen penPoint = new Pen(Color.Orange, 2);
                    // 
                    for (int i = 0; i < resultTrianglesTemp.Count; i++)
                    {
                        g.DrawEllipse(penPoint, (float)resultTrianglesTemp[i][0][0] - 2, (float)resultTrianglesTemp[i][0][1] - 2, 4, 4);
                        g.DrawEllipse(penPoint, (float)resultTrianglesTemp[i][1][0] - 2, (float)resultTrianglesTemp[i][1][1] - 2, 4, 4);
                        g.DrawEllipse(penPoint, (float)resultTrianglesTemp[i][2][0] - 2, (float)resultTrianglesTemp[i][2][1] - 2, 4, 4);
                    }
                }
                // Координатные оси:
                Pen penOrtho = new Pen(Color.Gray, 1);
                // LeftRight ось:
                for (int i = 0; i < coordPointsLeftRight.Count; i++)
                    g.DrawLine(penOrtho, coordPointsLeftRight[i][0], coordPointsLeftRight[i][1]);
                // TopBottom ось:
                for (int i = 0; i < coordPointsTopBottom.Count; i++)
                    g.DrawLine(penOrtho, coordPointsTopBottom[i][0], coordPointsTopBottom[i][1]);
                // Вывести подписи по оси X:
                Font xFont = new Font("Arial", 12);
                for (int i = 0; i < coordPointsTopBottom.Count; i++)
                    g.DrawString(i.ToString(), xFont, Brushes.Gray, (float)coordPointsTopBottom[i][0].X, (float)(shiftV + 10));
                // Вывести подписи по оси Y:
                for (int i = 0; i < coordPointsLeftRight.Count; i++)
                    g.DrawString(i.ToString(), xFont, Brushes.Gray, (float)10, (float)(coordPointsLeftRight[i][0].Y - 20));
                //
                g.Dispose();
            }
        }

        private void MainForm_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (_show == false)
                {
                    _show = true;
                }
                else
                {
                    _show = false;
                }
                //
                this.Refresh();
            }
        }

        /// <summary>
        /// Изменить параметры отрисовки/мастабирования.
        /// </summary>
        private void bthReDraw_Click(object sender, EventArgs e)
        {
            _compliete = false;
            zoom = Convert.ToInt32(tbZoom.Text);
            shiftH = Convert.ToInt32(tbShiftH.Text);
            shiftV = Convert.ToInt32(tbShiftV.Text);
            Layer = Convert.ToInt32(tbLayer.Text);
            //shiftCoords();
            shiftCoordsCustom(Layer);
            _compliete = true;
            this.Refresh();
        }

        /// <summary>
        /// Пересчет масштаба/сдвига координат.
        /// </summary>
        private void shiftCoords()
        {
            trianglesTemp = new List<double[][]>();
            resultTrianglesTemp = new List<double[][]>();
            
            for (int i = 0; i < triangles.Count; i++)
            {
                // выделить память.
                double[][] temp = new double[3][];
                for (int j = 0; j < temp.Length; j++)
                    temp[j] = new double[2];
                // копировать значения.
                for (int j = 0; j < temp.Length; j++)
                {
                    temp[j][0] = triangles[i][j][0]; // x.
                    temp[j][1] = triangles[i][j][1]; // y.
                }
                trianglesTemp.Add(temp);
            }

            for (int i = 0; i < resultTriangles.Count; i++)
            {
                // выделить память.
                double[][] temp = new double[3][];
                for (int j = 0; j < temp.Length; j++)
                    temp[j] = new double[2];
                // копировать значения.
                for (int j = 0; j < temp.Length; j++)
                {
                    temp[j][0] = resultTriangles[i][j][0]; // x.
                    temp[j][1] = resultTriangles[i][j][1]; // y.
                }
                resultTrianglesTemp.Add(temp);
            }

            for (int i = 0; i < triangles.Count; i++)
            {
                trianglesTemp[i][0][0] *= zoom; trianglesTemp[i][0][1] *= zoom;
                trianglesTemp[i][1][0] *= zoom; trianglesTemp[i][1][1] *= zoom;
                trianglesTemp[i][2][0] *= zoom; trianglesTemp[i][2][1] *= zoom;
                //
                trianglesTemp[i][0][0] = shiftH + trianglesTemp[i][0][0];
                trianglesTemp[i][1][0] = shiftH + trianglesTemp[i][1][0];
                trianglesTemp[i][2][0] = shiftH + trianglesTemp[i][2][0];
                //
                trianglesTemp[i][0][1] = shiftV - trianglesTemp[i][0][1];
                trianglesTemp[i][1][1] = shiftV - trianglesTemp[i][1][1];
                trianglesTemp[i][2][1] = shiftV - trianglesTemp[i][2][1];
            }

            for (int i = 0; i < resultTriangles.Count; i++)
            {
                resultTrianglesTemp[i][0][0] *= zoom; resultTrianglesTemp[i][0][1] *= zoom;
                resultTrianglesTemp[i][1][0] *= zoom; resultTrianglesTemp[i][1][1] *= zoom;
                resultTrianglesTemp[i][2][0] *= zoom; resultTrianglesTemp[i][2][1] *= zoom;
                //
                resultTrianglesTemp[i][0][0] = shiftH + resultTrianglesTemp[i][0][0];
                resultTrianglesTemp[i][1][0] = shiftH + resultTrianglesTemp[i][1][0];
                resultTrianglesTemp[i][2][0] = shiftH + resultTrianglesTemp[i][2][0];
                //
                resultTrianglesTemp[i][0][1] = shiftV - resultTrianglesTemp[i][0][1];
                resultTrianglesTemp[i][1][1] = shiftV - resultTrianglesTemp[i][1][1];
                resultTrianglesTemp[i][2][1] = shiftV - resultTrianglesTemp[i][2][1];
            }

            // рассчет координат осей.
            coordPointsLeftRight = new List<Point[]>();
            coordPointsTopBottom = new List<Point[]>();

            for (int i = 0; i < coordMaxY; i++)
            {
                Point[] temp = new Point[2];

                temp[0].X = 0 * zoom;
                temp[0].Y = i * zoom;
                temp[1].X = coordMaxX * zoom;
                temp[1].Y = i * zoom;

                temp[0].X = shiftH + temp[0].X;
                temp[1].X = shiftH + temp[1].X;

                temp[0].Y = shiftV - temp[0].Y;
                temp[1].Y = shiftV - temp[1].Y;

                coordPointsLeftRight.Add(temp);
            }

            for (int i = 0; i < coordMaxX; i++)
            {
                Point[] temp = new Point[2];

                temp[0].X = i * zoom;
                temp[0].Y = 0 * zoom;
                temp[1].X = i * zoom;
                temp[1].Y = coordMaxY * zoom;

                temp[0].X = shiftH + temp[0].X;
                temp[1].X = shiftH + temp[1].X;

                temp[0].Y = shiftV - temp[0].Y;
                temp[1].Y = shiftV - temp[1].Y;

                coordPointsTopBottom.Add(temp);
            }
        }

        /// <summary>
        /// Пересчет масштаба/сдвига координат (заданный слой)
        /// </summary>
        /// <param name="Layer">Номер этапа.</param>
        private void shiftCoordsCustom(int Layer)
        {
            trianglesTemp = new List<double[][]>();
            resultTrianglesTemp = new List<double[][]>();

            for (int i = 0; i < triangles.Count; i++)
            {
                // выделить память.
                double[][] temp = new double[3][];
                for (int j = 0; j < temp.Length; j++)
                    temp[j] = new double[2];
                // копировать значения.
                for (int j = 0; j < temp.Length; j++)
                {
                    temp[j][0] = triangles[i][j][0]; // x.
                    temp[j][1] = triangles[i][j][1]; // y.
                }
                trianglesTemp.Add(temp);
            }

            for (int n = 0; n < coalLayers[Layer].Count; n++)
            {
                for (int i = 0; i < coalLayers[Layer][n].trianlges.Count; i++)
                {
                    // выделить память.
                    double[][] temp = new double[3][];
                    for (int j = 0; j < temp.Length; j++)
                        temp[j] = new double[2];
                    // копировать значения.
                    for (int j = 0; j < temp.Length; j++)
                    {
                        temp[j][0] = coalLayers[Layer][n].trianlges[i][j][0]; // x.
                        temp[j][1] = coalLayers[Layer][n].trianlges[i][j][1]; // y.
                    }
                    resultTrianglesTemp.Add(temp);
                }
            }

            for (int i = 0; i < trianglesTemp.Count; i++)
            {
                trianglesTemp[i][0][0] *= zoom; trianglesTemp[i][0][1] *= zoom;
                trianglesTemp[i][1][0] *= zoom; trianglesTemp[i][1][1] *= zoom;
                trianglesTemp[i][2][0] *= zoom; trianglesTemp[i][2][1] *= zoom;
                //
                trianglesTemp[i][0][0] = shiftH + trianglesTemp[i][0][0];
                trianglesTemp[i][1][0] = shiftH + trianglesTemp[i][1][0];
                trianglesTemp[i][2][0] = shiftH + trianglesTemp[i][2][0];
                //
                trianglesTemp[i][0][1] = shiftV - trianglesTemp[i][0][1];
                trianglesTemp[i][1][1] = shiftV - trianglesTemp[i][1][1];
                trianglesTemp[i][2][1] = shiftV - trianglesTemp[i][2][1];
            }

            for (int i = 0; i < resultTrianglesTemp.Count; i++)
            {
                resultTrianglesTemp[i][0][0] *= zoom; resultTrianglesTemp[i][0][1] *= zoom;
                resultTrianglesTemp[i][1][0] *= zoom; resultTrianglesTemp[i][1][1] *= zoom;
                resultTrianglesTemp[i][2][0] *= zoom; resultTrianglesTemp[i][2][1] *= zoom;
                //
                resultTrianglesTemp[i][0][0] = shiftH + resultTrianglesTemp[i][0][0];
                resultTrianglesTemp[i][1][0] = shiftH + resultTrianglesTemp[i][1][0];
                resultTrianglesTemp[i][2][0] = shiftH + resultTrianglesTemp[i][2][0];
                //
                resultTrianglesTemp[i][0][1] = shiftV - resultTrianglesTemp[i][0][1];
                resultTrianglesTemp[i][1][1] = shiftV - resultTrianglesTemp[i][1][1];
                resultTrianglesTemp[i][2][1] = shiftV - resultTrianglesTemp[i][2][1];
            }

            // рассчет координат осей.
            coordPointsLeftRight = new List<Point[]>();
            coordPointsTopBottom = new List<Point[]>();

            for (int i = 0; i < coordMaxY; i++)
            {
                Point[] temp = new Point[2];

                temp[0].X = 0 * zoom;
                temp[0].Y = i * zoom;
                temp[1].X = coordMaxX * zoom;
                temp[1].Y = i * zoom;

                temp[0].X = shiftH + temp[0].X;
                temp[1].X = shiftH + temp[1].X;

                temp[0].Y = shiftV - temp[0].Y;
                temp[1].Y = shiftV - temp[1].Y;

                coordPointsLeftRight.Add(temp);
            }

            for (int i = 0; i < coordMaxX; i++)
            {
                Point[] temp = new Point[2];

                temp[0].X = i * zoom;
                temp[0].Y = 0 * zoom;
                temp[1].X = i * zoom;
                temp[1].Y = coordMaxY * zoom;

                temp[0].X = shiftH + temp[0].X;
                temp[1].X = shiftH + temp[1].X;

                temp[0].Y = shiftV - temp[0].Y;
                temp[1].Y = shiftV - temp[1].Y;

                coordPointsTopBottom.Add(temp);
            }
        }

        /// <summary>
        /// Таблица истинности для укладки.
        /// </summary>
        /// <param name="p">текущая схема.</param>
        /// <param name="q">принадлежность слою.</param>
        private static bool boolCoalSampling(bool p, bool q)
        {
            // 0 | 0 = 0 
            // 0 | 1 = 1
            // 1 | 0 = 1
            // 1 | 1 = 1
            if (p == false && q == false) return false;
            return true;
        }

        /// <summary>
        /// Таблица истинности для забора.
        /// </summary>
        /// <param name="p">текущая схема.</param>
        /// <param name="q">принадлежность слою.</param>
        private static bool boolCoalStowage(bool p, bool q)
        {
            // 0 | 0 = 0 
            // 0 | 1 = 0
            // 1 | 0 = 1
            // 1 | 1 = 0
            if (p == true && q == false) return true;
            return false;
        }

        /// <summary>
        /// Таблица истинности для укладки (перезапись информации).
        /// </summary>
        /// <param name="p">текущая схема.</param>
        /// <param name="q">принадлежность слою.</param>
        /// <returns></returns>
        private static bool boolCoalRewrite(bool p, bool q)
        {
            // 0 | 0 = 0 
            // 0 | 1 = 1
            // 1 | 0 = 0
            // 1 | 1 = 0
            if (p == false && q == true) return true;
            return false;
        }

        /// <summary>
        /// Формирование списка слоев для каждого этапа.
        /// </summary>
        /// <param name="_colorsOfLayers">Списк цветов каждого слоя.</param>
        /// <param name="_operations">Список типов операций.</param>
        /// <param name="_resultTriangles">Список малых треугольников.</param>
        /// <param name="_isInTriangle">Список принадлежности малых треугольников большим.</param>
        private static List<List<CoalLayer>> formationTheLayerList(List<Color> _colorsOfLayers, List<int> _operations, List<double[][]> _resultTriangles, List<List<bool>> _isInTriangle)
        {
            List<List<CoalLayer>> resultListLayer = new List<List<CoalLayer>>();
            List<List<smallTriangleInfo>> resultSmallTriangleList = new List<List<smallTriangleInfo>>();
            
            // 1) Сформировать лист информации по малым треугольникам каждого слоя.
            for (int i = 0; i < _operations.Count; i++)
            {
                List<smallTriangleInfo> tempListInfo = new List<smallTriangleInfo>();
                for (int j = 0; j < _resultTriangles.Count; j++)
                    tempListInfo.Add(new smallTriangleInfo(false, 0, Color.White));
                resultSmallTriangleList.Add(tempListInfo);
            }

            // 2) Создать каракас.
            List<smallTriangleInfo> currentScheme = new List<smallTriangleInfo>();
            for (int i = 0; i < _resultTriangles.Count; i++)
                currentScheme.Add(new smallTriangleInfo(false, 0, Color.White));

            // 3) Определить слои.
            for (int i = 0; i < _operations.Count; i++)
            {
                switch (_operations[i])
                {
                    case 1: // укладка
                        for (int j = 0; j < _resultTriangles.Count; j++)
                        {
                            if (boolCoalRewrite(currentScheme[j].enable, _isInTriangle[i][j]) == true)
                            {
                                currentScheme[j].id = i;
                                currentScheme[j].color = _colorsOfLayers[i];
                            }
                            currentScheme[j].enable = boolCoalSampling(currentScheme[j].enable, _isInTriangle[i][j]);
                        }
                        for (int j = 0; j < _resultTriangles.Count; j++)
                            resultSmallTriangleList[i][j] = (smallTriangleInfo)currentScheme[j].Clone();
                        break;
                    case 2: // забор
                        for (int j = 0; j < _resultTriangles.Count; j++)
                        {
                            currentScheme[j].enable = boolCoalStowage(currentScheme[j].enable, _isInTriangle[i][j]);
                            if (currentScheme[j].enable == false)
                            {
                                currentScheme[j].id = 0;
                                currentScheme[j].color = Color.White;
                            }
                        }
                        for (int j = 0; j < _resultTriangles.Count; j++)
                            resultSmallTriangleList[i][j] = (smallTriangleInfo)currentScheme[j].Clone();
                        break;
                    default:
                        break;
                }
            }

            // 4) В каждой операции удалить неиспользованные треугольники.
            /*
            for (int i = 0; i < _operations.Count; i++)
            {
                for (int j = 0; j < resultSmallTriangleList[i].Count; j++)
                {
                    if (resultSmallTriangleList[i][j].enable == false)
                    {
                        resultSmallTriangleList[i].RemoveAt(j);
                        j--;
                    }
                }
            }
            */

            // 5) Из оставшихся сформировать группы по слоям.
            for (int i = 0; i < _operations.Count; i++)
            {
                List<CoalLayer> tempLayerList = new List<CoalLayer>();
                for (int n = 0; n < _operations.Count; n++)
                {
                    List<double[][]> tempPoints = new List<double[][]>();

                    for (int j = 0; j < resultSmallTriangleList[i].Count; j++)
                    {
                        if (resultSmallTriangleList[i][j].enable == true && resultSmallTriangleList[i][j].id == n)
                        {
                            double[][] temp = new double[3][];
                            for (int k = 0; k < temp.Length; k++)
                                temp[k] = new double[2];

                            temp[0][0] = _resultTriangles[j][0][0]; temp[0][1] = _resultTriangles[j][0][1];
                            temp[1][0] = _resultTriangles[j][1][0]; temp[1][1] = _resultTriangles[j][1][1];
                            temp[2][0] = _resultTriangles[j][2][0]; temp[2][1] = _resultTriangles[j][2][1];

                            tempPoints.Add(temp);
                        }
                    }

                    CoalLayer tempLayer = new CoalLayer(n, tempPoints, _colorsOfLayers[n]);
                    tempLayerList.Add(tempLayer);
                }
                resultListLayer.Add(tempLayerList);
            }

            //
            return resultListLayer;
        }

        /// <summary>
        /// Получение списка слоев для заданного этапа (для GDI+ визаулизации).
        /// </summary>
        /// <param name="_coalLayers">Список слоев по всем операциям.</param>
        /// <param name="_Layer">Номер операции.</param>
        /// <param name="_zoom">Масштаб.</param>
        /// <param name="_shiftH">Сдвиг по горизонтали (pix).</param>
        /// <param name="_shiftV">Сдвиг по вертикали (pix).</param>
        private static List<List<double[][]>> getLayerList(List<List<CoalLayer>> _coalLayers, int _Layer, int _zoom, int _shiftH, int _shiftV)
        {
            List<List<double[][]>> resultList = new List<List<double[][]>>();
            //
            for (int n = 0; n < _coalLayers[_Layer].Count; n++)
            {
                List<double[][]> tempList = new List<double[][]>();
                for (int i = 0; i < _coalLayers[_Layer][n].trianlges.Count; i++)
                {
                    // выделить память.
                    double[][] temp = new double[3][];
                    for (int j = 0; j < temp.Length; j++)
                        temp[j] = new double[2];
                    // копировать значения.
                    for (int j = 0; j < temp.Length; j++)
                    {
                        temp[j][0] = _coalLayers[_Layer][n].trianlges[i][j][0]; // x.
                        temp[j][1] = _coalLayers[_Layer][n].trianlges[i][j][1]; // y.
                    }
                    tempList.Add(temp);
                }
                resultList.Add(tempList);
            }
            //
            for (int n = 0; n < resultList.Count; n++)
            {
                for (int i = 0; i < resultList[n].Count; i++)
                {
                    resultList[n][i][0][0] *= _zoom; resultList[n][i][0][1] *= _zoom;
                    resultList[n][i][1][0] *= _zoom; resultList[n][i][1][1] *= _zoom;
                    resultList[n][i][2][0] *= _zoom; resultList[n][i][2][1] *= _zoom;
                    //
                    resultList[n][i][0][0] = _shiftH + resultList[n][i][0][0];
                    resultList[n][i][1][0] = _shiftH + resultList[n][i][1][0];
                    resultList[n][i][2][0] = _shiftH + resultList[n][i][2][0];
                    //
                    resultList[n][i][0][1] = _shiftV - resultList[n][i][0][1];
                    resultList[n][i][1][1] = _shiftV - resultList[n][i][1][1];
                    resultList[n][i][2][1] = _shiftV - resultList[n][i][2][1];
                }
            }
            //
            return resultList;
        }
    }
}
